package services

import (
	"errors"
	"finance/internal/dto"
	"finance/internal/models"
	"gorm.io/gorm"
)

func GetTransactions(role string, userID uint, accountNo string, offset, limit int) ([]models.Transaction, int64, error) {
	db := models.DB.Model(&models.Transaction{}).Order("created_time DESC")

	// 筛选逻辑
	if role == "customer" {
		var accounts []models.Account
		if err := models.DB.Where("owner_user_id = ?", userID).Find(&accounts).Error; err != nil {
			return nil, 0, errors.New("无法查询用户账户")
		}
		if len(accounts) == 0 {
			return nil, 0, errors.New("该用户没有账户")
		}
		var ids []uint
		for _, acc := range accounts {
			ids = append(ids, acc.ID)
		}
		db = db.Where("account_id IN ?", ids)

	} else if role == "cashier" {
		if accountNo != "" {
			var account models.Account
			if err := models.DB.Where("account_no = ?", accountNo).First(&account).Error; err != nil {
				return nil, 0, errors.New("账户号不存在")
			}
			db = db.Where("account_id = ?", account.ID)
		}
	}
	// auditor 不加限制

	var (
		transactions []models.Transaction
		total        int64
	)
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}
	if err := db.Offset(offset).Limit(limit).Find(&transactions).Error; err != nil {
		return nil, 0, err
	}

	return transactions, total, nil
}

func Deposit(req *dto.DepositRequest, operatorID uint) error {
	if req.Amount <= 0 {
		return errors.New("invalid deposit amount")
	}

	var account models.Account // Transaction表需要account表中的account_id
	if err := models.DB.Where("account_no = ?", req.AccountNo).First(&account).Error; err != nil {
		return errors.New("account not found")
	}

	// Transaction用于开启一个数据库事务,确保一组操作要么完全成功,要么完全回滚
	return models.DB.Transaction(func(tx *gorm.DB) error {
		account.Balance += req.Amount
		// Save()用于更新或者插入记录,会根据主键判断
		if err := tx.Save(&account).Error; err != nil {
			return err
		}

		txn := models.Transaction{
			AccountID:  account.ID,
			Type:       "deposit",
			Amount:     req.Amount,
			OperatorID: operatorID,
			Remark:     "Deposit by user",
		}
		return tx.Create(&txn).Error
	})
}

func Withdraw(accountID uint, amount float64, operatorID uint, isCashier bool) error {
	if amount <= 0 {
		return errors.New("invalid withdraw amount")
	}

	var account models.Account
	if err := models.DB.First(&account, accountID).Error; err != nil {
		return errors.New("account not found")
	}

	if account.Balance < amount {
		return errors.New("insufficient balance")
	}

	if !isCashier && amount > 1000 {
		return errors.New("customer withdraw limit exceeded(max 1000)")
	}

	return models.DB.Transaction(func(tx *gorm.DB) error {
		account.Balance -= amount
		if err := tx.Save(&account).Error; err != nil {
			return err
		}

		txn := models.Transaction{
			AccountID:  account.ID,
			Type:       "withdraw",
			Amount:     amount,
			OperatorID: operatorID,
			Remark:     "Withdraw by user",
		}
		return tx.Create(&txn).Error
	})
}
